`:top
Das `!Explicitly Parallel Instruction Computing`! (`!EPIC`!) bezeichnet ein `F33f`_`[Programmierparadigma`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Programmierparadigma]`_`f einer `F33f`_`[Befehlssatzarchitektur`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Befehlssatzarchitektur]`_`f (`F33f`_`[englisch`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Englische_Sprache]`_`f `*Instruction Set Architecture`*, kurz `*ISA`*) und der Verarbeitungsstruktur einer Familie von `F33f`_`[Mikroprozessoren`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Mikroprozessor]`_`f, z. B. `F33f`_`[Itanium`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Itanium]`_`f. Bei der `F33f`_`[Programmierung`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Programmierung]`_`f von EPIC-CPUs wird die Parallelisierung der Befehle eines Instruktionsstromes explizit vorgenommen. Die ISA hat Eigenschaften, die die explizite `F33f`_`[Parallelisierung`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Parallele_Programmierung]`_`f unterstützen, während eine herkömmliche ISA von einer sequentiellen Abarbeitung der Befehle ausgeht. Ein Programm, das in einer Nicht-EPIC-`F33f`_`[Maschinensprache`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Maschinensprache]`_`f vorliegt, kann auch parallelisiert werden, aber es ist bei der Ausführung eine komplexe `F33f`_`[Logik`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Logikgatter]`_`f notwendig, um parallel ausführbare Instruktionen zu identifizieren, da das Befehlsformat keine Aussagen über parallelisierbare Instruktionen macht. Eine EPIC-`F33f`_`[CPU`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Hauptprozessor]`_`f arbeitet nach dem Prinzip der `F33f`_`[in-order Execution`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=In-order_execution]`_`f, im Gegensatz zur out-of-order execution der `F33f`_`[superskalaren`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Superskalarität]`_`f CPUs.
Die Motivation zur Entwicklung eines EPIC-Prozessors ist die Reduktion der `F33f`_`[Logikgatter`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Logikgatter]`_`f des Prozessors. Der nun frei gewordene Platz kann dazu benutzt werden, weitere funktionale Einheiten (z. B. Rechenwerke) in die CPU zu integrieren, um
• die Anzahl der parallel ausführbaren Operationen zu erhöhen,
• größere `F33f`_`[Caches`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Cache]`_`f in den Prozessor zu integrieren,
• den Einfluss des Flaschenhalses `*Hauptspeicher`* zu verringern oder
• den Stromverbrauch, die Verlustleistung und damit die Wärmeabgabe zu reduzieren.
Die out-of-order execution ist teilweise auch aus dem Zwang zur Rückwärtskompatibilität zu älteren Prozessoren entstanden. Da das Befehlsformat eines älteren Prozessors weiterhin unterstützt werden musste, konnten Verbesserungen zur parallelen Ausführung nur unter der Haube geschehen. Prinzipiell ist es aber möglich, den `F33f`_`[Compiler`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Compiler]`_`f mit dieser Aufgabe zu betrauen, und in den meisten Fällen ist ein Compiler für diese Aufgabe besser geeignet, da er mehr Zeit auf die Optimierung aufwenden kann und Zugriff auf mehr Informationen über den Programmfluss hat.
>>Contents
• `F0af`_`[Merkmale`#merkmale]`_`f
• `F0af`_`[Realisierung`#realisierung]`_`f
• `F0af`_`[Eigenschaften`#eigenschaften]`_`f
• `F0af`_`[Statische Befehlsgruppierung`#statische-befehlsgruppierung]`_`f
• `F0af`_`[Predication`#predication]`_`f
• `F0af`_`[Speculation`#speculation]`_`f
-─
>>Merkmale
Die wichtigsten Merkmale dieser Befehlssatzarchitektur sind:
• Statische Befehlsgruppierung: Der Compiler legt fest, welche Befehle parallel abgearbeitet werden können. Dadurch wird der Prozessor wesentlich einfacher (Pentium 4 mit 42 Millionen Transistorfunktionen, Itanium mit 25 Millionen Transistorfunktionen).
• `F33f`_`[VLIW`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Very_Long_Instruction_Word]`_`f-Architektur: Der Prozessor erhält very long instruction words, welche mehrere Befehle und die Aussage enthalten, auf welcher Einheit des Prozessors der Befehl auszuführen ist. Bei der IA-64 werden drei Befehle in ein VLIW gepackt.
• predication: Unter Predication (Aussage, Behauptung) versteht man die bedingte Ausführung von Befehlen ohne Verwendung von Sprungbefehlen.
• speculation: Damit im Befehlsablauf nicht auf Daten gewartet werden muss, können Daten zu einem frühen Zeitpunkt spekulativ geladen und bearbeitet werden.
• Load/Store-Architektur: Speicherzugriffe kommen nur bei Load- und Store-Befehlen vor (und natürlich beim `F33f`_`[Fetch-Zyklus`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Von-Neumann-Zyklus]`_`f).
• Große Registersätze: Die Load/Store-Architektur benötigt viele Register, um die Anzahl der Speicherzugriffe möglichst klein zu halten.
• register stack und register engine: Die Register sind so angeordnet, dass innerhalb einer Prozedur die statischen Register und die von der Prozedur verwendeten Register sichtbar sind. Die Register werden beim Prozeduraufruf dynamisch umbenannt. Die register engine sichert die im Moment nicht sichtbaren Register bei Bedarf im Speicher, so dass für ein Anwenderprogramm die Anzahl Register unbeschränkt ist.
• Leistungsfähiger Befehlssatz: Der Befehlssatz enthält eine große Anzahl leistungsfähiger, für Parallelverarbeitung geeignete Befehle.
• little-endian und big-endian: In einem Steuerregister des Prozessors kann man definieren, wie der Prozessor die Daten im Speicher ablegen soll.
>>Realisierung
Beim EPIC wird dem Prozessor bei der `F33f`_`[Programmierung`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Programmierung]`_`f signalisiert, welche `F33f`_`[Instruktionen`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Instruktion]`_`f parallel ausführbar sind. Solche parallelisierbaren Instruktionen werden in Gruppen `*(instruction groups)`* zusammengefasst. Die Instruktionen einer Gruppe können dann prinzipiell in beliebiger Reihenfolge und mit beliebigem Parallelitätsgrad ausgeführt werden.
Um die abhängigen Instruktionen voneinander zu trennen, müssen `*stops`* in den Befehlstrom eingebaut werden. Stops markieren das Ende einer `*instruction group`* und den Beginn einer Neuen. Die eigentlich `*explizite`* Parallelisierungsinformation sind die `*stops,`* denn durch sie werden parallelisierbare Instruktionen identifiziert, ohne dass eine Analyse erfolgen muss.
Das Optimierungsziel eines gegebenen EPIC-Programmes ist, die Anzahl der nötigen `*instruction groups`* zu minimieren, also die durchschnittliche Anzahl der Instruktionen pro `*instruction group`* zu erhöhen.
Dabei gibt es Ausnahmen (beim Beispiel IA-64). Zum Beispiel müssen `*Exceptions,`* die durch eine frühe Instruktion einer Gruppe ausgelöst werden immer so ausgeführt werden, als ob die späteren Instruktionen einer Gruppe gar nicht ausgeführt worden sind. Beliebige Instruktionen können aber spekulativ bereits ausgeführt worden sein, deren Ergebnis wird beim Auftauchen einer Exception einer früheren Instruktion verworfen. Der Prozessor muss also den Anschein erwecken, dass die Instruktionen einer Gruppe in Reihenfolge ausgeführt wurden. Andere Ausnahmen betreffen spezielle Instruktionen, die per definition am Anfang oder Ende einer `*instruction group`* vorkommen müssen.
>>Eigenschaften
Durch das EPIC spart man `F33f`_`[Ressourcen`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Ressource]`_`f, die bei Nicht-EPIC-Prozessoren dazu verwendet werden müssen, die Instruktionen während der Ausführung auf die parallel arbeitenden Einheiten des Prozessors aufzuteilen. Diese Einsparungen sind die Motivation für die Erfindung von EPIC. Es können dadurch die Kosten des Chips gesenkt werden, und die Leistungsaufnahme wird verringert. Die Berechnungen, die zur Parallelisierung des Befehlsstromes notwendig sind, werden bei EPIC einmal beim Kompilieren vorgenommen, bei Nicht-EPIC-Prozessoren jedes Mal bei der Ausführung des Codes und mithilfe einer recht großen Anzahl von Logikgattern.
Moderne Compiler nehmen auch für Nicht-EPIC-ISAs-Optimierungen des Befehlsstromes vor (verschieben z. B. unabhängige Instruktionen innerhalb des Stromes), um den Prozessor bei der Parallelisierung zu unterstützen. Bei EPIC-ISA ist diese Unterstützung des Prozessors zwingend, das heißt man kann einen Abhängigkeitsfehler erzeugen, selbst wenn die Instruktionen in der richtigen sequentiellen Reihenfolge stehen.
EPIC ist mit `F33f`_`[VLIW`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Very_Long_Instruction_Word]`_`f verwandt, denn VLIW dient auch dem Gruppieren von Instruktionen. Dabei muss beachtet werden, dass die VLIW-Gruppierung in `*Bundles`* und die EPIC-Gruppierung in `*instruction groups`* bei der `F33f`_`[IA-64`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=IA-64]`_`f voneinander unabhängig sind, das heißt zu einer `*instruction group`* gehören eine beliebige Anzahl von `*Bundles`* und ein `*stop`* kann auch zwischen Instruktionen eines einzelnen `*Bundles`* eingebracht werden.
ISAs, die EPIC als Architekturmerkmal haben, sind relativ schwer in `F33f`_`[Assemblersprache`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Assemblersprache]`_`f zu programmieren, und Compiler sind ein beträchtliches Maß komplexer, weil die Parallelisierung nun nicht mehr von der Implementierung der ISA, also dem Prozessor, selbst geleistet wird, sondern explizit erfolgen muss. So gibt es Sachverhalte bei der EPIC-Programmierung, die sich mit Nicht-EPIC-Maschinensprache gar nicht ausdrücken lassen, weil dort das Modell eine strikt sequentielle Ausführung ist.
Da die Berechnungen, die für die Parallelisierung notwendig sind, unabhängig von der Ausführung erfolgen, kann mehr Rechenzeit auf ebendiese Aufgabe verwendet werden.
>>Statische Befehlsgruppierung
Statische Befehlsgruppierung bedeutet, dass der Compiler für die Gruppierung parallel ablaufender Befehle zuständig ist. Wichtig ist dabei, dass der Compiler für die Architektur des Prozessors optimiert sein muss, um die Eigenschaften des Prozessors auszunutzen. Der Compiler gruppiert die Befehle so, dass möglichst viele parallel abgearbeitet werden können. Zusätzlich legt er fest, was für eine Einheit im Prozessor für die Bearbeitung des Befehls benötigt wird und markiert die Befehle entsprechend. Die Befehle werden dem Prozessor in Gruppen übergeben und aufgrund der vom Compiler festgelegten Zuordnung auf Prozessor-Einheiten verteilt und bearbeitet.
>>Predication
Predication ist ein Verfahren, Befehle abhängig von einer Bedingung auszuführen, ohne Sprungbefehle einzusetzen. Das Verfahren wird im Folgenden vereinfacht dargestellt: Die Ausführung eines Befehls kann vom Inhalt eines Predicate-Registers abhängen. Im folgenden Beispiel wird der MOV-Befehl nur ausgeführt, wenn das Predicate-Register `B100`F9d9p1`f`b true ist; ansonsten wirkt er wie ein NOP.
`B100`F9d9p1 mov gr8 = gr5 ; lade gr8 mit dem Wert von gr5 falls p1 = true`f`b
`B100`F9d9 ; falls p1 = false, wirkt der Befehl wie ein`f`b
`B100`F9d9 ; NOP`f`b
Die Predicate-Register können mit Compare-Befehlen gesetzt werden. Der folgende Compare-Befehl testet die Register `B100`F9d9gr10`f`b und `B100`F9d9gr11`f`b auf Gleichheit. Das Predicate-Register `B100`F9d9p1`f`b wird mit Resultat, das Register `B100`F9d9p2`f`b mit dessen Negation geladen.
`B100`F9d9 cmp.eq p1,p2 = gr10,gr11 ; teste gr10 mit gr11 auf equal`f`b
`B100`F9d9 ; falls equal: p1 true, p2 false`f`b
`B100`F9d9 ; falls not equal: p1 false, p2 true`f`b
>>Speculation
Je schneller die Prozessoren werden, desto größer ist der Verlust, wenn Daten vom Speicher geladen werden müssen und der Prozessor auf diese Daten warten muss. Darum ist das Ziel, Befehle im Programmablauf früher auszuführen, damit die benötigten Daten vorhanden sind, wenn sie benötigt werden.
Im ersten Beispiel muss nach dem Ladebefehl gewartet werden, bis die Daten in `B100`F9d9gr4`f`b resp. in `B100`F9d9gr5`f`b geladen sind. Im zweiten Beispiel wurde die Befehlsreihenfolge vertauscht und damit der Abstand zwischen voneinander abhängigen Befehlen vergrößert.
`B100`F9d9ld gr4, x`f`b
`B100`F9d9add gr4 = gr4,gr8`f`b
`B100`F9d9st y, gr4`f`b
`B100`F9d9ld gr5, a`f`b
`B100`F9d9add gr5 = gr5,gr9`f`b
`B100`F9d9st b, gr5`f`b
`B100`F9d9ld gr4, x`f`b
`B100`F9d9ld gr5, a`f`b
`B100`F9d9add gr4 = gr4,gr8`f`b
`B100`F9d9add gr5 = gr5,gr9`f`b
`B100`F9d9st y, gr4`f`b
`B100`F9d9st b, gr5`f`b
In vielen Fällen genügt es aber nicht, einen Befehl um einen oder zwei Befehle vorzuverlegen, da der Unterschied zwischen der Dynamik des Prozessors und dem Speicher zu groß ist. Die Verarbeitung der Daten muss warten, bis die Daten geladen wurden. Das Laden der Daten soll darum so weit vorverlegt werden, dass kein Warten notwendig ist.
Wird ein Ladebefehl wie im untenstehenden Beispiel über eine Verzweigung vorverlegt, so spricht man von einer `!Control Speculation.`! Tritt beim Laden ein Fehler auf, so soll dieser nicht behandelt werden, da man ja noch nicht weiß, ob man die Daten überhaupt benötigt. Das Laden erfolgt spekulativ. Bevor die Daten verarbeitet werden, muss aber geprüft werden, ob beim Laden ein Fehler aufgetreten ist und behoben werden muss. Die zweite Art der Spekulation ist die `!Data Speculation.`! Die große Anzahl von Arbeitsregistern erlaubt es viele Datenelemente in Registern zu halten. Um zu verhindern, dass beim Laden auf Daten gewartet werden muss, werden die benötigten Daten frühzeitig in Register geladen. Die folgende Befehlsfolge zeigt ein Beispiel für einen normalen Load. Der Befehl `B100`F9d9add gr5=gr2,gr7`f`b kann erst durchgeführt werden, wenn die Daten aus dem Speicher in `B100`F9d9gr2`f`b geladen wurden.
`B100`F9d9add gr3 = 4,gr0`f`b
`B100`F9d9st [gr32] = gr3`f`b
`B100`F9d9ld gr2 = [gr33]`f`b
`B100`F9d9add gr5 = gr2,gr7`f`b
Der Prozessor merkt sich darum alle vorzeitig geladenen Adressen im `!Advanced Load Address Table`! (ALAT). Im folgenden Beispiel beinhaltet der Load-Befehl eine Control Speculation da eine Verzweigung zwischen Laden und Verarbeitung liegt und eine Data Speculation, da der Store-Befehl mit dem Pointer `B100`F9d9[gr32]`f`b den geladenen Wert betreffen könnte. Es handelt sich um einen Speculative Advanced Load. Falls beim `B100`F9d9ld.sa`f`b ein Fehler auftritt, wird kein ALAT-Eintrag erstellt. Falls der Ladevorgang fehlerfrei abläuft, wird ein Eintrag im ALAT gemacht. Falls der Wert an der Adresse `B100`F9d9[gr33]`f`b verändert wird, so wird der ALAT-Eintrag gelöscht.
`B100`F9d9 ld.sa gr2 = [gr33] ; speculative advanced load`f`b
`B100`F9d9 ...`f`b
`B100`F9d9 add gr5 = gr2,gr7 ; use data`f`b
`B100`F9d9 ...`f`b
`B100`F9d9 ...`f`b
`B100`F9d9 add gr3 = 4,gr0`f`b
`B100`F9d9 st [gr32] = gr3`f`b
`B100`F9d9 ...`f`b
`B100`F9d9 cmp.eq p3,p4 = gr7,gr8`f`b
`B100`F9d9 p3 chk.a gr2,recover ; prüft ALAT`f`b
`B100`F9d9back: p3 add gr9 = 1, gr6`f`b
`B100`F9d9 ...`f`b
`B100`F9d9 ...`f`b
`B100`F9d9recover: ld gr2 = [gr33]`f`b
`B100`F9d9 add gr5 = gr2,gr7`f`b
`B100`F9d9 br back`f`b
Der Wert wird nicht nur vorzeitig gelesen `B100`F9d9ld.a gr2 = [gr33]`f`b, sondern auch bearbeitet `B100`F9d9add gr5 = gr2,gr7`f`b. Falls das verwendete Datenelement durch eine Operation verändert wird (z. B. durch `B100`F9d9st [gr32] = gr3`f`b), so wird dies durch den Check-Befehl festgestellt (`B100`F9d9chk.a gr2,recover`f`b), da der Eintrag im ALAT fehlt.
`c`F0af`_`[↑ Back to top`#top]`_`f`a